package com.easylinkin.linkappapi.dashboard.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.bases.redis.util.RedisUtil;
import com.easylinkin.linkappapi.common.service.CommonService;
import com.easylinkin.linkappapi.dashboard.entity.Dashboard;
import com.easylinkin.linkappapi.dashboard.mapper.DashboardMapper;
import com.easylinkin.linkappapi.dashboard.service.DashboardService;
import com.easylinkin.linkappapi.openapi.util.HttpClientUtil;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import com.easylinkin.linkappapi.security.service.LinkappUserService;
import com.easylinkin.linkappapi.tenant.entity.LinkappTenant;
import com.easylinkin.linkappapi.tenant.sevice.LinkappTenantService;
import io.netty.util.internal.StringUtil;
import java.lang.reflect.InvocationTargetException;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicHeader;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import site.morn.framework.entity.BaseUser;
import sun.misc.BASE64Encoder;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 大屏管理表 服务实现类
 * </p>
 *
 * @author Chenjunjie
 * @since 2020-07-07
 */
@Service
@Slf4j
public class DashboardServiceImpl extends ServiceImpl<DashboardMapper, Dashboard> implements DashboardService,
    InitializingBean {

    @Resource
    private CommonService commonService;

    @Resource
    private LinkappTenantService linkappTenantService;

    @Resource
    LinkappUserContextProducer linkappUserContextProducer;

    @Autowired
    private LinkappUserService linkappUserService;

    @Resource
    private RedissonClient redissonClient;

    @Value("${dashboard.bim.bimAppKey:eEHnZtmB1HM5VIzZ4f0PmbrsO9qGAjpk}")
    String bimAppKey ;
    @Value("${dashboard.bim.bimAppSecret:KUBwCWhxNt0eUTRZ3zBZn5SSwkd8ZfsT}")
    String bimAppSecret ;
    @Value("${dashboard.bim.bimOauth2TokenUrl:https://api.bimface.com/oauth2/token}")
    String bimOauth2TokenUrl;
    @Value("${dashboard.bim.bimTokenUrl:https://api.bimface.com/view/token}")
    String bimTokenUrl;


    @Override
    public boolean addDashboard(Dashboard dashboard) {
        //Assert.notNull(dashboard.getName(),"大屏名称不能为空");
        LinkappUser user = null;
        if (dashboard.getTenantId() == null) {
            commonService.setCreateAndModifyInfo(dashboard);
            user = linkappUserContextProducer.getCurrent();
            dashboard.setTenantId(user.getTenantId());
        }
        Dashboard dash = getDashboardByTenantId(dashboard.getTenantId());
        if (dash == null) {
            if (StringUtils.isEmpty(dashboard.getName())) {
                if (user == null) {
                    user = linkappUserContextProducer.getCurrent();
                }
                //如果名称为空，则自动生成，格式：租户名+"的大屏"+4为随机字符串
                dashboard.setName(user.getUsername() + "的大屏" + RandomStringUtils.randomAlphanumeric(4));
            }
            return this.save(dashboard);
        } else {
            dashboard.setId(dash.getId());
            if (StringUtils.isEmpty(dashboard.getName())) {
                //如果为空则不修改，虽然有null忽略策略，避免传双引号
                dashboard.setName(dash.getName());
            }
            return this.updateById(dashboard);
        }
    }

    @Override
    public void createIfNotExist(LinkappTenant tenant) {
        Dashboard dash = getDashboardByTenantId(tenant.getId());
        if(dash==null){
            dash = new Dashboard();
            dash.setTenantId(tenant.getId());
            //获取租户
            LinkappUser user = new LinkappUser();
            user.setType("1");
            user.setTenantId(tenant.getId());
            List<LinkappUser> linkappUsers = linkappUserService.selectUsers(user);
            if(CollectionUtil.isNotEmpty(linkappUsers)){
                try {
                    commonService.setCreateModifyInfo(linkappUsers.get(0),dash);
                    dash.setName(linkappUsers.get(0).getUsername() + "的大屏" + RandomStringUtils.randomAlphanumeric(4));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }
            }
            dash.setDashboardUrl("easyv-3d/bigscreen.html#/wisdomSite");
            this.save(dash);
        }
    }

    @Override
    public boolean updateDashboard(Dashboard dashboard) {
        if (dashboard.getTenantId() == null) {
            commonService.setModifyInfo(dashboard);
            LinkappUser user = linkappUserContextProducer.getCurrent();
            dashboard.setTenantId(user.getTenantId());
        }
        Dashboard dash = getDashboardByTenantId(dashboard.getTenantId());
        dashboard.setId(dash.getId());
        if (StringUtils.isEmpty(dashboard.getName())) {
            //如果为空则不修改，虽然有null忽略策略，避免传双引号
            dashboard.setName(dash.getName());
        }
        return this.updateById(dashboard);
    }

    @Override
    public boolean deleteDashboard(List<String> dashboardList) {
        Assert.notEmpty(dashboardList, "删除大屏列表不能为空");
        baseMapper.deleteBatchIds(dashboardList);
        return true;
    }

    @Override
    public IPage<Dashboard> getPage(IPage page, Dashboard dashboard) {
        Assert.notNull(page, "分页数据不能为空");
        Assert.notNull(dashboard, "查询对象不能为空");
        QueryWrapper<Dashboard> wrapper = new QueryWrapper<>();
        wrapper.like("name", dashboard.getName());
        wrapper.orderByDesc("modify_time");
        dashboard.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        return baseMapper.selectPage(page, wrapper);
    }

    @Override
    public Dashboard getDashboardByName(String name) {
        QueryWrapper<Dashboard> wrapper = new QueryWrapper<>();
        wrapper.like("name", name);
        List<Dashboard> dashboards = baseMapper.selectList(wrapper);
        return dashboards.get(0);
    }

    @Override
    public Dashboard getDashboardById(String id) {
        Dashboard dashboard = baseMapper.selectById(id);
        Assert.notNull(dashboard, "大屏不存在");
        return dashboard;
    }

    @Override
    public Dashboard getDashboardByTenantId(String tenantId) {
        QueryWrapper<Dashboard> wrapper = new QueryWrapper<>();
        wrapper.eq("tenant_id", tenantId);
        Dashboard dashboard = baseMapper.selectOne(wrapper);
        return dashboard;
    }

    @Override
    public List<Dashboard> getList() {
        QueryWrapper<Dashboard> wrapper = new QueryWrapper<>();
        wrapper.eq("tenant_id", linkappUserContextProducer.getNotNullCurrent().getTenantId());
        wrapper.orderByDesc("modify_time");
        List<Dashboard> dashboards = baseMapper.selectList(wrapper);
        if (!dashboards.isEmpty()) {
            Dashboard dashboard = dashboards.get(0);
            String integrateId = dashboard.getBimId();
            if (!StringUtils.isEmpty(integrateId)){
                dashboard.setIntegrateId(integrateId);
                String bimId = getBimId(integrateId);
                dashboard.setBimId(bimId);
            }
        }
        return dashboards;
    }


    /**
     * https://bimface.com/docs/model-service/v1/api-reference/api/getAccessTokenUsingPOST.html
     * 获取Token
     */
    private String getToken() {
        HttpPost httpPost = new HttpPost(bimOauth2TokenUrl);
        StringEntity se = null;
        try {
            se = new StringEntity(StringUtil.EMPTY_STRING);
        } catch (UnsupportedEncodingException e) {
            log.error("请求bim token 报错", e);
        }
        se.setContentType("application/json");
        se.setContentEncoding(new BasicHeader("Content-Type", "application/json"));
        httpPost.setEntity(se);
        log.info("请求bim url:" + bimOauth2TokenUrl);
        BASE64Encoder base64 = new BASE64Encoder();
        String ss = "Basic" + " " + base64.encode((bimAppKey + ":" + bimAppSecret).getBytes());
        httpPost.setHeader("Authorization", ss);

        String str = HttpClientUtil.doPost(httpPost);
        log.info("请求bim getToken:" + str);
        JSONObject jsonObject = JSON.parseObject(str);
        Map data = (Map) jsonObject.get("data");
        if (data != null) {
            String tokenStr = (String) data.get("token");
            log.info(tokenStr);
            return tokenStr;
        }
        return null;
    }

    private String getBimId(String integrateId) {
        String token = getToken();
        HttpGet httpGet = new HttpGet(bimTokenUrl + "?integrateId=" + integrateId);
        log.info("请求bim url:" + bimTokenUrl + "?integrateId=" + integrateId);
        String ss = "Bearer " + token;
        httpGet.setHeader("Authorization", ss);

        String str = HttpClientUtil.doGet(httpGet);
        log.info("请求bim getToken:" + str);
        JSONObject jsonObject = JSON.parseObject(str);
        String data = (String) jsonObject.get("data");
        log.info("获取token:{}", data);
        return data;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        RLock redissonLock = redissonClient.getLock("dashbordInit");
        if (redissonLock.tryLock()){
            try {
                List<LinkappTenant> linkappTenants = linkappTenantService.selectAll();
                if(CollectionUtil.isNotEmpty(linkappTenants)){
                    linkappTenants.forEach(item->{
                        createIfNotExist(item);
                    });
                }
            }catch (Exception e){
                log.error("update2发生错误", e);
                e.printStackTrace();
            }finally {
                if (redissonLock.isLocked() && redissonLock.isHeldByCurrentThread()) {
                    redissonLock.unlock();
                }
            }
        }
    }
}
